package pl.edu.agh.ssm.monitor.data;

import java.net.InetAddress;
import java.rmi.server.UID;
import java.util.HashMap;

import pl.edu.agh.ssm.monitor.utils.SessionDataUtils;

import jlibrtp.RtcpPkt;

/**
 * Node represents multimedia session participant.
 * It contains ip address, rtp ssrc, node type and
 * additional description informations.
 * @author Tomasz Jadczyk
 *
 */
public class SessionNode implements SessionData {

	/**
	 * IP address
	 */
	private InetAddress address;
	/**
	 * Node type (Sender, Receiver, Multiplexer, SenderAndReceiver)
	 */
	private SessionNodeType nodeType;
	/**
	 * Rtp ssrc value
	 */
	private long ssrc;

	private String id;
	private String sessionID;

	/* Node state variables */
	private long lastMixerInfoTime = -1;
	private long lastReceiverInfoTime = -1;
	private long lastSenderInfoTime = -1;
	
	/* It shouldn't be null when node is sender */
	private SenderReportInfo senderInfo = null;
	/**
	 * Last report of each report type
	 */
	private HashMap<Class<? extends RtcpPkt>, RtcpPkt> reports;
	private HashMap<SessionNodeType, Long> lastActivityTime; //map contains time of this node
	private long lastReportTime = 0;															//last activity report 
	
	private SessionNodeDescription nodeDescription;
	
	public SessionNode(InetAddress address, String sessionID) {
		this.address = address;
		this.sessionID = sessionID;
		this.id = new UID().toString();
		reports = new HashMap<Class<? extends RtcpPkt>, RtcpPkt>();
		lastActivityTime = new HashMap<SessionNodeType, Long>();
		lastReportTime = System.currentTimeMillis();
	}
	
	public InetAddress getAddress() {
		return address;
	}
	
	public SessionNodeType getNodeType() {
		return nodeType;
	}

	public void setNodeType(SessionNodeType nodeType) {
		lastActivityTime.put(nodeType, new Long(System.currentTimeMillis()));
		this.nodeType = SessionDataUtils.getSessionNodeType(lastActivityTime);
		this.lastReportTime = System.currentTimeMillis();
	}
	
	public void setNodeTypeDirectly(SessionNodeType nodeType) {
		this.nodeType = nodeType;
	}

	public long getSsrc() {
		return ssrc;
	}
	
	public HashMap<SessionNodeType, Long> getStates() {
		return lastActivityTime;
	}

	public void setSsrc(long ssrc) {
		this.ssrc = ssrc;
	}
	
	public void setReport(RtcpPkt report) {
		this.reports.put(report.getClass(), report);
	}
	
	public RtcpPkt getReport(Class<? extends RtcpPkt> reportType) {
		return this.reports.get(reportType);
	}
	
/* -----------------------------------------------------------------------
 * Methods for comparison Node objects.
 * -----------------------------------------------------------------------
 */
	@Override
	public boolean equals(Object obj) {
		if (obj instanceof SessionNode) {
			SessionNode newNode = (SessionNode) obj;
			return newNode.getId().equals(this.getId());
		}
		return false;
	}
	
	@Override
	public int hashCode() {
		return this.getId().hashCode();
	}

	@Override
	public String getId() {
		return id;
	}

	public SessionNodeDescription getNodeDescription() {
		return nodeDescription;
	}

	public void setNodeDescription(SessionNodeDescription nodeDescription) {
		this.nodeDescription = nodeDescription;
	}
	
	public String getSessionId() {
		return sessionID;
	}

	public long getLastMixerInfoTime() {
		return lastMixerInfoTime;
	}

	public void setLastMixerInfoTime(long lastMixerInfoTime) {
		this.lastMixerInfoTime = lastMixerInfoTime;
	}

	public long getLastReceiverInfoTime() {
		return lastReceiverInfoTime;
	}

	public void setLastReceiverInfoTime(long lastReceiverInfoTime) {
		this.lastReceiverInfoTime = lastReceiverInfoTime;
	}

	public long getLastSenderInfoTime() {
		return lastSenderInfoTime;
	}

	public void setLastSenderInfoTime(long lastSenderInfoTime) {
		this.lastSenderInfoTime = lastSenderInfoTime;
	}

	public SenderReportInfo getSenderInfo() {
		return senderInfo;
	}

	public void setSenderInfo(SenderReportInfo senderInfo) {
		this.senderInfo = senderInfo;
	}

	public long getLastReportTime() {
		return lastReportTime;
	}
	
}
